#include<pthread.h>
#include<iostream>
#include<unistd.h>
using namespace std;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
// void* Run(void * args)
// {
//    pthread_mutex_lock(&lock);
//    cout << "1 1 1 " << endl;
// }
// void* Run1(void * args)
// {
//     cout << "6 6 6" << endl;
//     pthread_mutex_lock(&lock);
//     cout << "? ? ? " << endl;
// }
// int main()
// {
//     // pthread_mutex_lock(&mutex);
//     // int n = pthread_mutex_trylock(&mutex);
//     // cout << strerror(n) << endl;
//     pthread_t pid;
//     pthread_create(&pid,nullptr,Run,nullptr);

//     pthread_join(pid,nullptr);
//     pthread_create(&pid,nullptr,Run1,nullptr);
//     pthread_join(pid,nullptr);
    
    
//     return 0;
// }

// pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
// pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;

// // 线程1的执行函数：先获取mutex1，再尝试获取mutex2
// void *thread1_func(void *arg) {
//     printf("线程1: 尝试获取mutex1...\n");
//     pthread_mutex_lock(&mutex1);
//     printf("线程1: 已获取mutex1\n");
    
//     // 休眠一小段时间，让线程2有机会获取mutex2，增加死锁概率
//     sleep(1);
    
//     printf("线程1: 尝试获取mutex2...\n");
//     pthread_mutex_lock(&mutex2);
//     printf("线程1: 已获取mutex2\n");
    
//     // 执行一些操作...
//     printf("线程1: 正在执行操作\n");
    
//     // 释放资源
//     pthread_mutex_unlock(&mutex2);
//     printf("线程1: 已释放mutex2\n");
//     pthread_mutex_unlock(&mutex1);
//     printf("线程1: 已释放mutex1\n");
    
//     return NULL;
// }

// // 线程2的执行函数：先获取mutex2，再尝试获取mutex1
// void *thread2_func(void *arg) {
//     printf("线程2: 尝试获取mutex1...\n");
//     pthread_mutex_lock(&mutex1);
//     printf("线程2: 已获取mutex2\n");
    
//     // 休眠一小段时间，让线程1有机会获取mutex1，增加死锁概率
//     sleep(1);
    
//     printf("线程2: 尝试获取mutex2...\n");
//     pthread_mutex_lock(&mutex2);
//     printf("线程2: 已获取mutex1\n");
    
//     // 执行一些操作...
//     printf("线程2: 正在执行操作\n");
    
//     // 释放资源
//     pthread_mutex_unlock(&mutex1);
//     printf("线程2: 已释放mutex1\n");
//     pthread_mutex_unlock(&mutex2);
//     printf("线程2: 已释放mutex2\n");
    
//     return NULL;
// }

// int main() {
//     pthread_t thread1, thread2;
    
//     // 创建两个线程
//     pthread_create(&thread1, NULL, thread1_func, NULL);
//     pthread_create(&thread2, NULL, thread2_func, NULL);
    
//     // 等待线程结束
//     pthread_join(thread1, NULL);
//     pthread_join(thread2, NULL);
    
//     // 销毁互斥锁
//     pthread_mutex_destroy(&mutex1);
//     pthread_mutex_destroy(&mutex2);
    
//     printf("程序正常结束\n");
//     return 0;
// }


int cnt = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* Count(void* args)
{
   pthread_detach(pthread_self());
   uint64_t number = (uint64_t)args;
    while(true)
   {
     pthread_mutex_lock(&mutex);
     pthread_cond_wait(&cond,&mutex); //为什么在这里? ? ? 
     //让线程等待时,会自动释放锁! ! ! 
      // 我们怎么知道我们要让一个线程去休眠了那？一定是临界资源不就绪，没错，临界资源也是有状态的！！
 // 你怎么知道临界资源是就绪还是不就绪的？你判断出来的！判断是访问临界资源吗？必须是的，也就是判断必须在加锁之后！！！

     std::cout << "pthread: " << number << " , cnt: " << cnt++ << endl;
     usleep(500);
     pthread_mutex_unlock(&mutex);
   }
}

int main()
{
   for(uint64_t i = 0;i < 5;++i)
   {
     pthread_t tid;
     pthread_create(&tid,nullptr,Count,(void*)i);
   }
   sleep(3);
   cout << "main thread ctrl begin: " << endl;
   while(true) 
   {
    sleep(1);

    // pthread_cond_signal(&cond);//唤醒在cond的等待队列中的第一个线程
    pthread_cond_broadcast(&cond);
    cout << "signal one thread ..." << endl;
    //按顺序了! ! ! 

   }
   return 0;
}

// void *getTicket(void *args)
// {
//     threadData *td = static_cast<threadData *>(args);
//     const char *name = td->threadname.c_str();
//     while (true)
//     {
//         // 线程对于锁的竞争能力可能会不同 --- 一会由例子
//         // pthread_mutex_lock(td->lock); // 申请锁成功，才能往后执行，不成功，阻塞等待。
//         pthread_mutex_lock(&lock); // 申请锁成功，才能往后执行，不成功，阻塞等待。
//         if(tickets > 0)
//         {
//             usleep(1000);
//             printf("who=%s, get a ticket: %d\n", name, tickets); // ?
//             tickets--;
//             pthread_mutex_unlock(td->lock);
//             // pthread_mutex_unlock(&lock);
//         }
//         else{
//             pthread_mutex_unlock(td->lock);
//             // pthread_mutex_unlock(&lock);
//             // wait
//         }
//         usleep(13); // 我们抢到了票，我们会立马抢下一张吗？其实多线程还要执行得到票之后的后续动作。usleep模拟
//     }
//     printf("%s ... quit\n", name);
//     return nullptr;
// }